//===--- IntegerArithmetic.swift.gyb --------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
%# Ignore the following admonition; it applies to the resulting .swift file only

// Automatically Generated From IntegerArithmetic.swift.gyb.  Do Not Edit
// Directly!

%{
integerBinaryOps = [
  ('add', '+', 'Adds', 'the result'),
  ('subtract', '-', 'Subtracts', 'the result'),
  ('multiply', '*', 'Multiplies', 'the result'),
  ('divide', '/', 'Divides', 'the result'),
  ('remainder', '%', 'Divides', 'the remainder')
]
}%

/// This protocol is an implementation detail of `IntegerArithmetic`; do
/// not use it directly.
///
/// Its requirements are inherited by `IntegerArithmetic` and thus must
/// be satisfied by types conforming to that protocol.
@_show_in_interface
public protocol _IntegerArithmetic {
% for name, _, Action, result in integerBinaryOps:
  /// ${Action} `lhs` and `rhs`, returning ${result} and a `Bool` that is
  /// `true` iff the operation caused an arithmetic overflow.
  static func ${name}WithOverflow(_ lhs: Self, _ rhs: Self) -> (Self, overflow: Bool)
% end
}

/// The common requirements for types that support integer arithmetic.
public protocol IntegerArithmetic : _IntegerArithmetic, Comparable {
  // Checked arithmetic functions.  Specific implementations in
  // FixedPoint.swift.gyb support static checking for integer types.
% for name, op, Action, result in integerBinaryOps:
  /// ${Action} `lhs` and `rhs`, returning ${result} and trapping in case of
  /// arithmetic overflow (except in -Ounchecked builds).
  static func ${op} (lhs: Self, rhs: Self) -> Self
% end

  /// Explicitly convert to `IntMax`, trapping on overflow (except in
  /// -Ounchecked builds).
  func toIntMax() -> IntMax
}

% for name, op, Action, result in integerBinaryOps:
/// ${Action} `lhs` and `rhs`, returning ${result} and trapping in case of
/// arithmetic overflow (except in -Ounchecked builds).
@_transparent
public func ${op} <T : _IntegerArithmetic>(lhs: T, rhs: T) -> T {
  return _overflowChecked(T.${name}WithOverflow(lhs, rhs))
}

% if (op != '/') and (op != '%'):
/// ${Action} `lhs` and `rhs`, silently discarding any overflow.
@_transparent
public func &${op} <T : _IntegerArithmetic>(lhs: T, rhs: T) -> T {
  return T.${name}WithOverflow(lhs, rhs).0
}
% end

/// ${Action} `lhs` and `rhs` and stores ${result} in `lhs`, trapping in
/// case of arithmetic overflow (except in -Ounchecked builds).
@_transparent
public func ${op}= <T : _IntegerArithmetic>(lhs: inout T, rhs: T) {
  lhs = lhs ${op} rhs
}
% end

//===--- SignedNumber -----------------------------------------------------===//
// A numeric type that supports abs(x), +x and -x
//===----------------------------------------------------------------------===//

// SignedNumber itself contains only operator requirements having
// default implementations on the base protocol.
/// Instances of conforming types can be subtracted, arithmetically
/// negated, and initialized from `0`.
///
/// Axioms:
///
/// - `x - 0 == x`
/// - `-x == 0 - x`
/// - `-(-x) == x`
public protocol SignedNumber : Comparable, ExpressibleByIntegerLiteral {
  /// Returns the result of negating `x`.
  static prefix func - (x: Self) -> Self

  /// Returns the difference between `lhs` and `rhs`.
  static func - (lhs: Self, rhs: Self) -> Self

  // Do not use this operator directly; call abs(x) instead
  static func ~> (_:Self,_:(_Abs, ())) -> Self
}

// Unary negation in terms of subtraction.  This is a default
// implementation; models of SignedNumber can provide their own
// implementations.
@_transparent
public prefix func - <T : SignedNumber>(x: T) -> T {
  return 0 - x
}

// Unary +
@_transparent
public prefix func + <T : SignedNumber>(x: T) -> T {
  return x
}

//===--- abs(x) -----------------------------------------------------------===//
public struct _Abs {}

@_versioned
internal func _abs<Args>(_ args: Args) -> (_Abs, Args) {
  return (_Abs(), args)
}

// Do not use this operator directly; call abs(x) instead
@_transparent
public func ~> <T : SignedNumber>(x:T,_:(_Abs, ())) -> T {
  return x < 0 ? -x : x
}

// FIXME: should this be folded into SignedNumber?
/// A type that supports an "absolute value" function.
public protocol AbsoluteValuable : SignedNumber {
  /// Returns the absolute value of `x`.
  static func abs(_ x: Self) -> Self
}

// Do not use this operator directly; call abs(x) instead
@_transparent
public func ~> <T : AbsoluteValuable>(x:T,_:(_Abs, ())) -> T {
  return T.abs(x)
}

/// Returns the absolute value of `x`.
///
/// Concrete instances of `SignedNumber` can specialize this
/// function by conforming to `AbsoluteValuable`.
@_transparent
public func abs<T : SignedNumber>(_ x: T) -> T {
  return x~>_abs()
}

@available(*, unavailable, renamed: "IntegerArithmetic")
public typealias IntegerArithmeticType = IntegerArithmetic

@available(*, unavailable, renamed: "SignedNumber")
public typealias SignedNumberType = SignedNumber

// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
